package com.tianji.learning.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.Constants.RedisConstants;
import com.tianji.learning.domain.vo.SignRecordVO;
import com.tianji.learning.domain.vo.SignResultVO;
import com.tianji.learning.mq.message.SignInMessage;
import com.tianji.learning.service.ISignRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 学霸天梯榜 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-04-15
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class SignRecordServiceImpl  implements ISignRecordService {
    private final StringRedisTemplate redisTemplate;
    //private static final String SIGN_RECORD_KEY_PREFIX="sign:record:";
    private final RabbitMqHelper mqHelper;
    @Override
    public SignResultVO addSignRecord() {
        //1.获取当前用户id
        Long userId = UserContext.getUser();
        //2.获取当前时间
        LocalDateTime now = LocalDateTime.now();
        //3.格式化时间为yyyyMM
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyyMM");
        String format = now.format(timeFormatter);
        //4.获取当前时间是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //5.拼接key，签到记录的key是RedisConstants.SIGN_RECORD_KEY_PREFIX+userId+yyyyMM
        String key= RedisConstants.SIGN_RECORD_KEY_PREFIX+userId+format;
        //5.1获取当天签到记录，判断是否已经签过
        if (Boolean.TRUE.equals(redisTemplate.opsForValue().getBit(key, dayOfMonth - 1))){
            log.info("用户{}今天已经签到过了", userId);
            throw new BizIllegalException("今天已经签到过了,请勿重复签到");
        }
        //6.设置签到记录的key的value，value是当前用户是否签到，签到就是true，否则就是false
        redisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
        //7.获取签到记录  ：从0开始获取dayOfMonth条数据
        List<Long> bitField = redisTemplate.opsForValue().bitField(key,
                BitFieldSubCommands.create()
                        .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth))
                        .valueAt(0));
        if (CollUtil.isEmpty(bitField)) {
            log.info("获取签到记录失败");
            return null;
        }
        Long records = bitField.get(0);
        if (records == null || records == 0){
            return null;
        }
        int count=0;
        while ((records & 1) != 0) {
            count++;
            records >>>= 1;
        }
        SignResultVO vo = new SignResultVO();
        vo.setSignDays(count);
        if (count==28){
            vo.setSignPoints(41);
        } else if (count == 14) {
            vo.setSignPoints(21);
        } else if (count == 7) {
            vo.setSignPoints(11);
        }else {
            vo.setSignPoints(1);
        }
        log.info("用户{}签到成功，连续签到{}天，签到积分{}", userId, count, vo.getSignPoints());
        //发送签到积分消息
        SignInMessage message = new SignInMessage();
        message.setUserId(userId);
        message.setPoints(vo.getSignPoints());
        mqHelper.send(
                MqConstants.Exchange.LEARNING_EXCHANGE,
                MqConstants.Key.SIGN_IN,
                message);// 签到积分是基本得分+奖励积分
        // 在SignRecordServiceImpl中添加测试日志
        log.info("发送MQ消息到交换机：{}，路由键：{}",
                MqConstants.Exchange.LEARNING_EXCHANGE,
                MqConstants.Key.SIGN_IN);
        return vo;
    }

    @Override
    public SignRecordVO queryTodaySignRecord() {
        //1.获取当前用户id
        Long userId = UserContext.getUser();
        //2.获取当前时间
        LocalDateTime now = LocalDateTime.now();
        //3.格式化时间为yyyyMM
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyyMM");
        String format = now.format(timeFormatter);
        //4.获取当前时间是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //5.拼接key，签到记录的key是RedisConstants.SIGN_RECORD_KEY_PREFIX+userId+yyyyMM
        String key= RedisConstants.SIGN_RECORD_KEY_PREFIX+userId+format;
        //5.1获取当天签到记录，判断是否已经签过
        /*List<Long> bitField = redisTemplate.opsForValue().bitField(key,
                BitFieldSubCommands.create()
                        .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth))
                        .valueAt(0));
        if (CollUtil.isEmpty(bitField)){
            throw new BizIllegalException("获取签到记录失败");
        }
        Long records = bitField.get(0);
        if (records == null || records == 0){
            return null;
        }
        SignRecordVO vo = new SignRecordVO();
        ArrayList<Byte> bytes = new ArrayList<>(dayOfMonth);
        int i=1;
        while(i<=dayOfMonth){
            if ((records & 1)==0){
                bytes.add((byte)0);
            }else {
                bytes.add((byte)1);
            }
            records >>>= 1;
            i++;
        }
        vo.setSignRecords(bytes);*/
        SignRecordVO vo = new SignRecordVO();
        ArrayList<Byte> list = new ArrayList<>(dayOfMonth);
        for (int i = 0; i <dayOfMonth; i++){
            if (Boolean.TRUE.equals(redisTemplate.opsForValue().getBit(key, i))){
                list.add((byte)1);
            }else {
                list.add((byte)0);
            }
        }
        vo.setSignRecords(list);
        return vo;
    }
}
